package org.dolphin.entity.security;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.ForeignKey;
import org.springframework.util.ObjectUtils;

@Entity
@Table(name = "MS_GROUP", uniqueConstraints = {@UniqueConstraint(columnNames = {"NAME"}, name = "UQ_MS_GROUP_NAME")})
public class Group implements Serializable {
  private static final long serialVersionUID = 1182810081485845201L;
  private Long id;
  private String name;
  private Long version;
  private Date createdDate;
  private User createdBy;
  private Date updatedDate;
  private User updatedBy;
  private List<UserGroup> userGroups;
  private List<AccessControl> accessControls;

  @Override
  public boolean equals(Object obj) {
    if (obj == this) {
      return true;
    } else if (obj instanceof Group) {
      Group oth = (Group) obj;
      return ObjectUtils.nullSafeEquals(getId(), oth.getId());
    }
    return false;
  }

  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(name = "MS_GROUP_ACCESS_CONTROL", joinColumns = @JoinColumn(name = "GROUP_ID"), inverseJoinColumns = @JoinColumn(name = "ACCESS_CONTROL_ID"))
  @Fetch(FetchMode.SUBSELECT)
  @ForeignKey(name = "FK_GROUP_ACCESS_CONTROL_GROUP", inverseName = "FK_GROUP_ACCESS_CONTROL_ACCESS_CONTROL")
  public List<AccessControl> getAccessControls() {
    return accessControls;
  }

  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "CREATED_BY", nullable = false)
  @ForeignKey(name = "FK_GROUP_CREATED_BY")
  public User getCreatedBy() {
    return createdBy;
  }

  @Temporal(TemporalType.TIMESTAMP)
  @Column(name = "CREATED_DATE", nullable = false)
  public Date getCreatedDate() {
    return createdDate;
  }

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "ID", nullable = false)
  public Long getId() {
    return id;
  }

  @Column(name = "NAME", nullable = false, length = 100)
  public String getName() {
    return name;
  }

  @ManyToOne(fetch = FetchType.LAZY, optional = true)
  @JoinColumn(name = "UPDATED_BY", nullable = true)
  @ForeignKey(name = "FK_GROUP_UPDATED_BY")
  public User getUpdatedBy() {
    return updatedBy;
  }

  @Temporal(TemporalType.TIMESTAMP)
  @Column(name = "UPDATED_DATE", nullable = true)
  public Date getUpdatedDate() {
    return updatedDate;
  }

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.group")
  @Fetch(FetchMode.SUBSELECT)
  @ForeignKey(name = "FK_USER_GROUP_GROUP")
  public List<UserGroup> getUserGroups() {
    return userGroups;
  }

  @Version
  @Column(name = "VERSION_NO", nullable = false)
  public Long getVersion() {
    return version;
  }

  @Override
  public int hashCode() {
    int hash = ObjectUtils.nullSafeHashCode(getId());
    return hash;
  }

  public void setAccessControls(List<AccessControl> accessControls) {
    this.accessControls = accessControls;
  }

  public void setCreatedBy(User createdBy) {
    this.createdBy = createdBy;
  }

  public void setCreatedDate(Date createdDate) {
    this.createdDate = createdDate;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setUpdatedBy(User updatedBy) {
    this.updatedBy = updatedBy;
  }

  public void setUpdatedDate(Date updatedDate) {
    this.updatedDate = updatedDate;
  }

  public void setUserGroups(List<UserGroup> userGroups) {
    this.userGroups = userGroups;
  }

  public void setVersion(Long version) {
    this.version = version;
  }
}
